class Solution {
public:
    int sets = 0;
    vector<int> father;
    void build(int n)
    {
        for (int i = 0; i < n; i++)
            father[i] = i;
        sets = n;
    }

    void set_union(int x, int y)
    {
        int fx = find(x);
        int fy = find(y);
        if (fx != fy)
        {
            father[fx] = fy;
            sets--;
        }
    }

    int find(int p)
    {
        if (father[p] != p)
        {
            father[p] = find(father[p]);
        }
        return father[p];
    }

    int numSimilarGroups(vector<string>& strs) {
        int n = strs.size();
        int m = strs[0].size();
        father.resize(n);
        build(n);
        for (int i = 0; i < n; i++)
        {
            for (int j = i + 1; j < n; j++)
            {
                int diff = 0;
                for (int k = 0; k < m && diff < 3; k++)
                {
                    if (strs[i][k] != strs[j][k])
                        diff++;
                }
                if (diff == 0 || diff == 2)
                    set_union(i, j);
            }
        }
        return sets;
    }
};
